package com.robusta.spreadsheet.describe.jaxb;

import com.robusta.spreadsheet.describe.ColumnInfo;
import com.robusta.spreadsheet.describe.Validatable;
import com.robusta.spreadsheet.describe.Validator;
import com.robusta.spreadsheet.describe.jaxb.validation.*;

import javax.xml.bind.annotation.*;
import java.util.Collections;
import java.util.List;

import static com.google.common.collect.Lists.newArrayList;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType
public class Column implements ColumnInfo, Validator {
    @XmlAttribute
    private boolean keyColumn;
    @XmlElement(namespace = "http://www.robusta-inc.com/describe-workbook")
    private String fieldName;
    @XmlElement(namespace = "http://www.robusta-inc.com/describe-workbook")
    private String headerText;
    @XmlElement(namespace = "http://www.robusta-inc.com/describe-workbook")
    private Validators validators; 

    public String modelFieldName() {
        return fieldName;
    }

    public String spreadsheetHeaderText() {
        return headerText;
    }

    public boolean isKey() {
        return keyColumn;
    }

    @Override
    public Validator validator() {
        return this;
    }

    public List<? extends com.robusta.spreadsheet.describe.jaxb.validation.Validator> getListOfValidators() {
        if(validators != null) {
            return validators.getValidators();
        }
        return Collections.emptyList();
    }

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType
    public static class Validators {
        @XmlElements({
                @XmlElement(name="mandatoryValidator", type=MandatoryValidator.class, namespace = "http://www.robusta-inc.com/describe-workbook"),
                @XmlElement(name="regexValidator", type=RegexValidator.class, namespace = "http://www.robusta-inc.com/describe-workbook"),
                @XmlElement(name="contentValidator", type=ContentValidator.class, namespace = "http://www.robusta-inc.com/describe-workbook")
        })
        private List<? extends BaseValidator> validators;

        public List<? extends BaseValidator> getValidators() {
            return validators;
        }
    }

    public ValidationResult runValidations(Validatable validatable) {
        ValidationResult result = new ValidationResult();
        for (com.robusta.spreadsheet.describe.jaxb.validation.Validator validator : getListOfValidators()) {
            try {
                validator.validate(validatable);
            } catch (ValidationException e) {
                result.addResult(e);
            }
        }
        return result;
    }
    
    private static class ValidationResult implements com.robusta.spreadsheet.describe.ValidationResult {
        private List<String> messages = newArrayList();

        public void addResult(ValidationException e) {
            messages.add(e.getMessage());
        }

        public boolean isValid() {
            return messages.isEmpty();
        }

        public List<String> messages() {
            return messages;
        }
    }
}
